﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TorchView.GameContent.Data;
using System.IO;

namespace TorchView.GameContent.Units
{
    public sealed class Item : IDataSerializable
    {
        public Item()
        {
            Wardrobes = new List<Wardrobe>(0);
            Effects = new List<Effect>(0);
            Skills = new List<UnitSkill>(0);

            #region defaultproperties
            Name = "";
            UnitGuid = 0;
            CreateAs = "";
            Shadows = false;
            DontCreate = false;
            DisplayName = "";
            UnidentifiedName = "";
            Description = "";
            ResourceDirectory = "";
            MeshFile = "";
            SecondaryMeshFile = "";
            TextureOverride = "";
            AttachedLayout = "";
            MinDamage = 0;
            MaxDamage = 0;
            Range = 0f;
            Speed = 0;
            StrikeRange = 0f;
            ElectricDamage = 0;
            IceDamage = 0;
            FireDamage = 0;
            PoisonDamage = 0;
            PhysicalDamage = 0;
            BlockChance = 0;
            UnitType = "";
            Rarity = 0;
            RarityHardcore = 0;
            MinLevel = 0;
            MaxLevel = 0;
            Level = 0;
            LevelRequired = 0;
            Value = 0;
            MaxStackSize = 0;
            Uses = "";
            TargetType = ""; //  new string[] { "", "USER", "ITEM" }
            Icon = "";
            IconSheet = 0;
            ArmorMin = 0;
            ArmorMax = 0;
            ElectricArmor = 0;
            IceArmor = 0;
            FireArmor = 0;
            PoisonArmor = 0;
            PhysicalArmor = 0;
            SpeedDamageMod = 0;
            RarityDamageMod = 0;
            SpecialDamageMod = 0;
            RarityArmorMod = 0;
            SpecialArmorMod = 0;
            FallSound = "";
            LandSound = "";
            TakeSound = "";
            UseSound = "";
            AttackSound = "";
            StrikeSound = "";
            Missile = "";
            Set = "";
            StrengthRequired = 0;
            DexterityRequired = 0;
            MagicRequired = 0;
            DefenseRequired = 0;
            DropArticle = "";
            GamblerIcon = "";
            Sockets = 0;
            #endregion
        }

        #region IDataSerializable Members

        public DataBlock MakeDataBlock()
        {
            throw new NotImplementedException();
        }

        public void LoadFromDataBlock(DataBlock block)
        {
            Data = block;
            string baseFile = block.GetPropertyValue("BASEFILE", "");
            bool dontCreate = block.GetPropertyValue("DONTCREATE", DontCreate); ;
            if (baseFile.Length > 0)
            {
                if (baseFile.EndsWith(".dat"))
                    baseFile += ".adm";

                Stream stream = PakReader.OpenFile(baseFile);
                DataBlock baseBlock = AdmSerializer.Load(stream);
                LoadFromDataBlock(baseBlock);
            }
            BaseFile = baseFile;
            DontCreate = dontCreate;
            
            Name = block.GetPropertyValue("NAME", Name);
            string Guid = block.GetPropertyValue("UNIT_GUID", "");
            if (Guid.Length > 0) UnitGuid = long.Parse(Guid);
            CreateAs = block.GetPropertyValue("CREATEAS", CreateAs);
            Shadows = block.GetPropertyValue("SHADOWS", Shadows);
            
            DisplayName = block.GetPropertyValue("DISPLAYNAME", DisplayName);
            UnidentifiedName = block.GetPropertyValue("UNIDENTIFIED_NAME", UnidentifiedName);
            Description = block.GetPropertyValue("DESCRIPTION", Description);
            ResourceDirectory = block.GetPropertyValue("RESOURCEDIRECTORY", ResourceDirectory);
            MeshFile = block.GetPropertyValue("MESHFILE", MeshFile);
            SecondaryMeshFile = block.GetPropertyValue("MESHFILE_SECONDARY", SecondaryMeshFile);
            TextureOverride = block.GetPropertyValue("TEXTURE_OVERRIDE", TextureOverride);
            AttachedLayout = block.GetPropertyValue("ATTACHEDLAYOUT", AttachedLayout);
            MinDamage = block.GetPropertyValue("MINDAMAGE", MinDamage);
            MaxDamage = block.GetPropertyValue("MAXDAMAGE", MaxDamage);
            Range = block.GetPropertyValue("RANGE", Range);
            Speed = block.GetPropertyValue("SPEED", Speed);
            StrikeRange = block.GetPropertyValue("STRIKERANGE", StrikeRange);
            ElectricDamage = block.GetPropertyValue("DAMAGE_ELECTRIC", ElectricDamage);
            IceDamage = block.GetPropertyValue("DAMAGE_ICE", IceDamage);
            FireDamage = block.GetPropertyValue("DAMAGE_FIRE", FireDamage);
            PoisonDamage = block.GetPropertyValue("DAMAGE_POISON", PoisonDamage);
            PhysicalDamage = block.GetPropertyValue("DAMAGE_PHYSICAL", PhysicalDamage);
            BlockChance = block.GetPropertyValue("BLOCK_CHANCE", BlockChance);
            UnitType = block.GetPropertyValue("UNITTYPE", UnitType);
            Rarity = block.GetPropertyValue("RARITY", Rarity);
            RarityHardcore = block.GetPropertyValue("RARITY_HARDCORE", RarityHardcore);
            MinLevel = block.GetPropertyValue("MINLEVEL", MinLevel);
            MaxLevel = block.GetPropertyValue("MAXLEVEL", MaxLevel);
            Level = block.GetPropertyValue("LEVEL", Level);
            LevelRequired = block.GetPropertyValue("LEVEL_REQUIRED", LevelRequired);
            Value = block.GetPropertyValue("VALUE", Value);
            MaxStackSize = block.GetPropertyValue("MAXSTACKSIZE", MaxStackSize);
            Uses = block.GetPropertyValue("USES", Uses);
            TargetType = block.GetPropertyValue("TARGET_TYPE", TargetType); //  new string[] { "", "USER", "ITEM" }
            Icon = block.GetPropertyValue("ICON", Icon);
            IconSheet = block.GetPropertyValue("ICON_SHEET", IconSheet);
            ArmorMin = block.GetPropertyValue("ARMORMIN", ArmorMin);
            ArmorMax = block.GetPropertyValue("ARMORMAX", ArmorMax);
            ElectricArmor = block.GetPropertyValue("ARMOR_ELECTRIC", ElectricArmor);
            IceArmor = block.GetPropertyValue("ARMOR_ICE", IceArmor);
            FireArmor = block.GetPropertyValue("ARMOR_FIRE", FireArmor);
            PoisonArmor = block.GetPropertyValue("ARMOR_POISON", PoisonArmor);
            PhysicalArmor = block.GetPropertyValue("ARMOR_PHYSICAL", PhysicalArmor);
            SpeedDamageMod = block.GetPropertyValue("SPEED_DMG_MOD", SpeedDamageMod);
            RarityDamageMod = block.GetPropertyValue("RARITY_DMG_MOD", RarityDamageMod);
            SpecialDamageMod = block.GetPropertyValue("SPECIAL_DMG_MOD", SpecialDamageMod);
            RarityArmorMod = block.GetPropertyValue("RARITY_AMR_MOD", RarityArmorMod);
            SpecialArmorMod = block.GetPropertyValue("SPECIAL_AMR_MOD", SpecialArmorMod);
            FallSound = block.GetPropertyValue("FALL_SOUND", FallSound);
            LandSound = block.GetPropertyValue("LAND_SOUND", LandSound);
            TakeSound = block.GetPropertyValue("TAKE_SOUND", TakeSound);
            UseSound = block.GetPropertyValue("USE_SOUND", UseSound);
            AttackSound = block.GetPropertyValue("ATTACK_SOUND", AttackSound);
            StrikeSound = block.GetPropertyValue("STRIKE_SOUND", StrikeSound);
            Missile = block.GetPropertyValue("MISSILE", Missile);
            Set = block.GetPropertyValue("SET", Set);
            StrengthRequired = block.GetPropertyValue("STRENGTH_REQUIRED", StrengthRequired);
            DexterityRequired = block.GetPropertyValue("DEXTERITY_REQUIRED", DexterityRequired);
            MagicRequired = block.GetPropertyValue("MAGIC_REQUIRED", MagicRequired);
            DefenseRequired = block.GetPropertyValue("DEFENSE_REQUIRED", DefenseRequired);
            DropArticle = block.GetPropertyValue("DROPPARTICLE", DropArticle);
            GamblerIcon = block.GetPropertyValue("GAMBLER_ICON", GamblerIcon);
            Sockets = block.GetPropertyValue("SOCKETS", Sockets);

            var affixes = block.GetSubBlock("AFFIXES");
            if (affixes != null)
                Affixes = affixes.GetProperties("AFFIX").Select(p => p.Value as string).Where(s => s != null).ToArray();
            else
                Affixes = new String[0];

            Wardrobes.Clear();
            Wardrobes.AddRange(block.SubBlocks.Select(s =>
            {
                if (s.Name != Wardrobe.BLOCK_NAME)
                    return null;
                Wardrobe w = new Wardrobe();
                w.LoadFromDataBlock(s);
                return w;
            }).Where(b => b != null));

            Effects.Clear();
            Effects.AddRange(block.SubBlocks.Select(s =>
            {
                if (s.Name != Effect.BLOCK_NAME)
                    return null;
                Effect e = new Effect();
                e.LoadFromDataBlock(s);
                return e;
            }).Where(b => b != null));

            Skills.Clear();
            Skills.AddRange(block.SubBlocks.Select(s =>
            {
                if (s.Name != UnitSkill.BLOCK_NAME)
                    return null;
                UnitSkill sk = new UnitSkill();
                sk.LoadFromDataBlock(s);
                return sk;
            }).Where(b => b != null));
        }

        #endregion

        public DataBlock Data { get; set; }
        public List<Wardrobe> Wardrobes { get; private set; }
        public List<Effect> Effects { get; private set; }
        public List<UnitSkill> Skills { get; private set; }

        public string Name { get; set; }
        public long UnitGuid { get; set; }
        public string DisplayName { get; set; }
        public string UnidentifiedName { get; set; }
        public string Description { get; set; }
        public string BaseFile { get; set; }
        public string ResourceDirectory { get; set; }
        public string MeshFile { get; set; }
        public string SecondaryMeshFile { get; set; }
        public string TextureOverride { get; set; }
        public string AttachedLayout { get; set; }
        public int MinDamage { get; set; }
        public int MaxDamage { get; set; }
        public float Range { get; set; }
        public int Speed { get; set; }
        public float StrikeRange { get; set; }
        public int ElectricDamage { get; set; }
        public int IceDamage { get; set; }
        public int FireDamage { get; set; }
        public int PoisonDamage { get; set; }
        public int PhysicalDamage { get; set; }
        public int BlockChance { get; set; }
        public string UnitType { get; set; }
        public int Rarity { get; set; }
        public int RarityHardcore { get; set; }
        public int MinLevel { get; set; }
        public int MaxLevel { get; set; }
        public int Level { get; set; }
        public int LevelRequired { get; set; }
        public int Value { get; set; }
        public int MaxStackSize { get; set; }
        public string Icon { get; set; }
        public string TargetType { get; set; }
        public string Uses { get; set; }
        public int ArmorMin { get; set; }
        public int ArmorMax { get; set; }
        public int ElectricArmor { get; set; }
        public int IceArmor { get; set; }
        public int FireArmor { get; set; }
        public int PoisonArmor { get; set; }
        public int PhysicalArmor { get; set; }
        public int SpeedDamageMod { get; set; }
        public int RarityDamageMod { get; set; }
        public int SpecialDamageMod { get; set; }
        public int RarityArmorMod { get; set; }
        public int SpecialArmorMod { get; set; }
        public string FallSound { get; set; }
        public string LandSound { get; set; }
        public string TakeSound { get; set; }
        public string UseSound { get; set; }
        public string AttackSound { get; set; }
        public string StrikeSound { get; set; }
        public string Missile { get; set; }
        public string Set { get; set; }
        public int StrengthRequired { get; set; }
        public int DexterityRequired { get; set; }
        public int MagicRequired { get; set; }
        public int DefenseRequired { get; set; }
        public string DropArticle { get; set; }
        public string GamblerIcon { get; set; }
        public string[] Affixes { get; set; }
        public string CreateAs { get; set; }
        public bool Shadows { get; set; }
        public bool DontCreate { get; set; }
        public int Sockets { get; set; }
        public int IconSheet { get; set; }
    }
}
